package com.singfan.app.controller;

import com.singfan.app.controller.model.HttpModelConverter;
import com.singfan.app.controller.model.request.*;
import com.singfan.app.controller.model.response.*;
import com.singfan.app.controller.model.response.partial.BarberPartial;
import com.singfan.app.controller.model.response.partial.CouponPartial;
import com.singfan.app.controller.model.response.partial.HairstylePartial;
import com.singfan.app.controller.model.response.partial.ShopSummaryPartial;
import com.singfan.app.util.RequestParamChecker;
import com.singfan.common.util.*;
import com.singfan.core.component.CustomerTokenHolder;
import com.singfan.core.dao.database.model.*;
import com.singfan.core.dao.database.model.constant.CollectType;
import com.singfan.core.dao.database.model.constant.GenderType;
import com.singfan.core.service.IShopService;
import com.singfan.core.util.SmsUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * Summary:
 * Author: james
 * Date: 2015-07-29 11:33
 * Desc:
 */
@Controller
public class CustomerController extends SingFanControllerBase {
    @Autowired
    private IShopService shopService;

    @RequestMapping(value="/v1/customer/securitycode", method=RequestMethod.POST)
    public void securityCode(HttpServletRequest request, HttpServletResponse response) {
        CustomerSecurityCodeResponse result = new CustomerSecurityCodeResponse();
        CustomerSecurityCodeRequest customerSecurityCodeRequest = request2Bean(request, CustomerSecurityCodeRequest.class);

        String securityCode = RandomUtil.randomNumber(6);
        String ip = getIpAddress(request);
        String phoneNumber = customerSecurityCodeRequest.getPhoneNumber();
        if (!StringUtil.isNullOrEmpty(phoneNumber)){
            boolean isDisabled = customerService.isDisabledAccount(phoneNumber);
            if (!isDisabled){
                boolean sendResult = SmsUtil.sendSecurityCode(phoneNumber, securityCode);

                if (sendResult){
                    customerService.createPhoneSecurityCode(phoneNumber, securityCode);
                    result.setResultCode(ResultCode.SUCCESS);
                    traceLog.debug(String.format("CustomerController.securityCode() successful -> resultCode:%1$d, ip:%2$s, phoneNumber:%3$s, securityCode:%4$s", ResultCode.SUCCESS, ip, phoneNumber, securityCode));
                }
                else {
                    result.setResultCode(ResultCode.SERVER_BUSY);
                    traceLog.error(String.format("CustomerController.securityCode() error with SERVER_BUSY -> resultCode:%1$d, ip:%2$s, phoneNumber:%3$s, securityCode:%4$s", ResultCode.REQUEST_PARAM_ERROR, ip, phoneNumber, securityCode));
                }
            }
            else {
                result.setResultCode(ResultCode.ACCOUNT_DISABLED);
                traceLog.error(String.format("CustomerController.securityCode() error with ACCOUNT_DISABLED -> resultCode:%1$d, ip:%2$s, phoneNumber:%3$s", ResultCode.ACCOUNT_DISABLED, ip, phoneNumber));
            }
        }
        else {
            result.setResultCode(ResultCode.REQUEST_PARAM_ERROR);
            traceLog.error(String.format("CustomerController.securityCode() error with REQUEST_PARAM_ERROR -> resultCode:%1$d, ip:%2$s, phoneNumber:%3$s", ResultCode.REQUEST_PARAM_ERROR, ip, phoneNumber));
        }

        bean2Response(response, result);
    }

    @RequestMapping(value="/v1/customer/login", method=RequestMethod.POST)
    public void login(HttpServletRequest request, HttpServletResponse response){
        CustomerLoginRequest customerLoginRequest = request2Bean(request, CustomerLoginRequest.class);
        String ip = getIpAddress(request);
        String phoneNumber = customerLoginRequest.getPhoneNumber();
        String securityCode = customerLoginRequest.getSecurityCode();
        String phoneType = customerLoginRequest.getPhoneType();
        int cityId = customerLoginRequest.getCityId();

        CustomerLoginResponse customerLoginResponse = new CustomerLoginResponse();

        boolean isDisabled = customerService.isDisabledAccount(phoneNumber);
        if (!isDisabled){
            boolean verifyResult = customerService.verifyPhoneSecurityCode(phoneNumber, securityCode);
            if (verifyResult) {
                Customer customer = customerService.createOrUpdateCustomer(phoneNumber, phoneType, cityId);
                customerLoginResponse.setResultCode(ResultCode.SUCCESS);
                String token = customerService.createAccessToken(customer.getId(), customer.getCityId());
                customerLoginResponse.setAccessToken(token);
                customerLoginResponse.setAvatar(customer.getAvatar());
                customerLoginResponse.setPhoneNumber(customer.getPhoneNumber());

                traceLog.debug(String.format("CustomerController.login() successful -> resultCode:%1$d, ip:%2$s, phoneNumber:%3$s, securityCode:%4$s, phoneType:%5$s, cityId:%6$d, token:%7$s", ResultCode.SUCCESS, ip, phoneNumber, securityCode, phoneType, cityId, token));
            }
            else {
                customerLoginResponse.setResultCode(ResultCode.SECURITY_CODE_ERROR);
                traceLog.error(String.format("CustomerController.login() error with SECURITY_CODE_ERROR -> resultCode:%1$d, ip:%2$s, phoneNumber:%3$s, securityCode:%4$s, phoneType:%5$s, cityId:%6$d", ResultCode.SECURITY_CODE_ERROR, ip, phoneNumber, securityCode, phoneType, cityId));
            }
        }
        else {
            customerLoginResponse.setResultCode(ResultCode.ACCOUNT_DISABLED);
            traceLog.error(String.format("CustomerController.login() error with ACCOUNT_DISABLED -> resultCode:%1$d, ip:%2$s, phoneNumber:%3$s, securityCode:%4$s, phoneType:%5$s, cityId:%6$d", ResultCode.ACCOUNT_DISABLED, ip, phoneNumber, securityCode, phoneType, cityId));
        }

        bean2Response(response, customerLoginResponse);
    }

    @RequestMapping(value="/v1/customer/detail", method=RequestMethod.POST)
    public void detail(HttpServletRequest request, HttpServletResponse response){
        CustomerDetailRequest customerDetailRequest = request2Bean(request, CustomerDetailRequest.class);
        String ip = getIpAddress(request);
        String accessToken = customerDetailRequest.getAccessToken();
        Customer customer = customerService.findCustomerByToken(accessToken);

        CustomerDetailResponse customerDetailResponse = new CustomerDetailResponse();
        if (customer != null){
            customerDetailResponse.setResultCode(ResultCode.SUCCESS);

            customerDetailResponse.setAvatar(customer.getAvatar());
            customerDetailResponse.setNickName(customer.getNickName());
            customerDetailResponse.setGender(customer.getGender());
            customerDetailResponse.setBirthday(customer.getBirthday());
            customerDetailResponse.setHairStyle(customer.getHairStyleId());
            customerDetailResponse.setLikeHairStyle(customer.getLikeHairStyle());
            customerDetailResponse.setCareer(customer.getCareer());
            customerDetailResponse.setPosition(customer.getPosition());
            customerDetailResponse.setPhoneNum(customer.getPhoneNumber());
            customerDetailResponse.setAddress(customer.getAddress());

            traceLog.error(String.format("CustomerController.detail() successful -> resultCode:%1$d, ip:%2$s, accessToken:%3$s", ResultCode.SUCCESS, ip, accessToken));
        }
        else {
            customerDetailResponse.setResultCode(ResultCode.ACCESS_TOKEN_ERROR);

            traceLog.error(String.format("CustomerController.detail() error with ACCESS_TOKEN_ERROR -> resultCode:%1$d, ip:%2$s, accessToken:%3$s", ResultCode.ACCESS_TOKEN_ERROR, ip, accessToken));
        }

        bean2Response(response, customerDetailResponse);
    }

    @RequestMapping(value="/v1/customer/update", method=RequestMethod.POST)
    public void update(HttpServletRequest request, HttpServletResponse response){
        CustomerDetailUpdateRequest customerDetailUpdateRequest = request2Bean(request, CustomerDetailUpdateRequest.class);
        String ip = getIpAddress(request);
        String accessToken = customerDetailUpdateRequest.getAccessToken();
        String nickName = customerDetailUpdateRequest.getNickName();
        String career = customerDetailUpdateRequest.getCareer();
        String position = customerDetailUpdateRequest.getPosition();
        String address = customerDetailUpdateRequest.getAddress();
        String birthday = customerDetailUpdateRequest.getBirthday();
        String avatar = customerDetailUpdateRequest.getAvatar();
        int gender = customerDetailUpdateRequest.getGender();

        Customer customer = customerService.findCustomerByToken(customerDetailUpdateRequest.getAccessToken());

        CustomerDetailUpdateResponse customerDetailUpdateResponse = new CustomerDetailUpdateResponse();
        if (customer != null){
            boolean checkResult = true;
            if (!StringUtil.isNullOrEmpty(nickName) && nickName.length() > 32) {
                checkResult = false;
            }
            else if(!StringUtil.isNullOrEmpty(career) && career.length() > 64) {
                checkResult = false;
            }
            else if(!StringUtil.isNullOrEmpty(position) && position.length() > 64) {
                checkResult = false;
            }
            else if(!StringUtil.isNullOrEmpty(address) && address.length() > 256) {
                checkResult = false;
            }
            else if(!GenderType.isGenderType(gender)) {
                checkResult = false;
            }

            if (checkResult){
                customer.setNickName(nickName);
                customer.setGender(gender);
                customer.setBirthday(birthday);
                customer.setHairStyleId(customerDetailUpdateRequest.getHairStyle());
                customer.setLikeHairStyle(customerDetailUpdateRequest.getLikeHairStyle());
                customer.setCareer(career);
                customer.setPosition(position);
                customer.setAddress(address);
                customer.setAvatar(avatar);

                customerService.updateCustomer(customer);

                customerDetailUpdateResponse.setResultCode(ResultCode.SUCCESS);

                traceLog.error(String.format("CustomerController.update() successful -> resultCode:%1$d, ip:%2$s, accessToken:%3$s, nickName:%4$s, career:%5$s, position:%6$s, address:%7$s, birthday:%8$s, gender:%9$d, avatar:%10$s", ResultCode.SUCCESS, ip, accessToken, nickName, career, position, address, birthday, gender, avatar));
            }
            else {
                customerDetailUpdateResponse.setResultCode(ResultCode.REQUEST_PARAM_ERROR);

                traceLog.error(String.format("CustomerController.update() error with REQUEST_PARAM_ERROR -> resultCode:%1$d, ip:%2$s, accessToken:%3$s, nickName:%4$s, career:%5$s, position:%6$s, address:%7$s, birthday:%8$s, gender:%9$d, avatar:%10$s", ResultCode.REQUEST_PARAM_ERROR, ip, accessToken, nickName, career, position, address, birthday, gender, avatar));
            }
        }
        else {
            customerDetailUpdateResponse.setResultCode(ResultCode.ACCESS_TOKEN_ERROR);

            traceLog.error(String.format("CustomerController.update() error with ACCESS_TOKEN_ERROR -> resultCode:%1$d, ip:%2$s, accessToken:%3$s, nickName:%4$s, career:%5$s, position:%6$s, address:%7$s, birthday:%8$s, gender:%9$d", ResultCode.ACCESS_TOKEN_ERROR, ip, accessToken, nickName, career, position, address, birthday, gender));
        }

        bean2Response(response, customerDetailUpdateResponse);
    }

    @RequestMapping(value="/v1/customer/collect", method=RequestMethod.POST)
    public void collect(HttpServletRequest request, HttpServletResponse response){
        CustomerCollectResponse result = new CustomerCollectResponse();
        CustomerCollectRequest customerCollectRequest = request2Bean(request, CustomerCollectRequest.class);

        String ip = getIpAddress(request);
        String accessToken = customerCollectRequest.getAccessToken();
        long itemID = customerCollectRequest.getItemID();
        int itemType = customerCollectRequest.getItemType();
        boolean actionType = customerCollectRequest.isActionType();

        CustomerToken customerToken = CustomerTokenHolder.getCurrentCustomerToken();
        if (customerToken != null) {
            long customerId = customerToken.getCustomerId();
            if (CollectType.isCollectType(itemType)){
                result.setResultCode(ResultCode.SUCCESS);
                boolean collected = customerService.isCollected(customerId, itemID, itemType);
                if (actionType){
                    if (!collected){
                        customerService.collect(customerId, itemID, itemType);
                    }
                    result.setCollected(true);
                }
                else {
                    if (collected) {
                        customerService.collectCancel(customerId, itemID, itemType);
                    }
                    result.setCollected(false);
                }

                traceLog.debug(String.format("CustomerController.collect() successful -> resultCode:%1$d, ip:%2$s, accessToken:%3$s, itemID:%4$d, itemType:%5$d, actionType:%6$b", ResultCode.SUCCESS, ip, accessToken, itemID, itemType, actionType));
            }
            else {
                result.setResultCode(ResultCode.REQUEST_PARAM_ERROR);

                traceLog.error(String.format("CustomerController.collect() error with REQUEST_PARAM_ERROR -> resultCode:%1$d, ip:%2$s, accessToken:%3$s, itemID:%4$d, itemType:%5$d, actionType:%6$b", ResultCode.REQUEST_PARAM_ERROR, ip, accessToken, itemID, itemType, actionType));
            }
        }
        else {
            result.setResultCode(ResultCode.ACCESS_TOKEN_ERROR);

            traceLog.error(String.format("CustomerController.collect() error with ACCESS_TOKEN_ERROR -> resultCode:%1$d, ip:%2$s, accessToken:%3$s, itemID:%4$d, itemType:%5$d, actionType:%6$b", ResultCode.ACCESS_TOKEN_ERROR, ip, accessToken, itemID, itemType, actionType));
        }

        bean2Response(response, result);
    }

    @RequestMapping(value="/v1/customer/collect/list", method=RequestMethod.POST)
    public void collectList(HttpServletRequest request, HttpServletResponse response){
        CustomerCollectListResponse result = new CustomerCollectListResponse();
        CustomerCollectListRequest customerCollectListRequest = request2Bean(request, CustomerCollectListRequest.class);
        String ip = getIpAddress(request);
        String accessToken = customerCollectListRequest.getAccessToken();
        int itemType = customerCollectListRequest.getItemType();
        int pageIndex = customerCollectListRequest.getPageIndex();
        int pageSize = customerCollectListRequest.getPageSize();
        String longitudeStr = customerCollectListRequest.getLongitude();
        String latitudeStr = customerCollectListRequest.getLatitude();

        CustomerToken customerToken = CustomerTokenHolder.getCurrentCustomerToken();
        if (customerToken != null) {
            long customerId = customerToken.getCustomerId();

            boolean checkResult = true;
            if (!CollectType.isCollectType(itemType)) {
                checkResult = false;
            }
            else if(!RequestParamChecker.checkPageIndexAndSize(pageIndex, pageSize)) {
                checkResult = false;
            }
            else if(!RequestParamChecker.checkLongitude(longitudeStr)) {
                checkResult = false;
            }
            else if(!RequestParamChecker.checkLatitude(latitudeStr)) {
                checkResult = false;
            }

            if (checkResult){
                double longitude = Double.parseDouble(longitudeStr);
                double latitude = Double.parseDouble(latitudeStr);
                List<CustomerCollect> collectList = customerService.findCollectList(customerId, itemType, pageIndex, pageSize);
                List<Long> idList = new ArrayList<>(collectList.size());
                for (CustomerCollect customerCollect : collectList) {
                    idList.add(customerCollect.getCollectId());
                }
                if (itemType == CollectType.SHOP){
                    List<ShopHair> shopHairList = shopService.findShopHairList(idList);
                    List<ShopSummaryPartial> shopSummaryPartialList = new ArrayList<>(shopHairList.size());
                    for (ShopHair shopHair : shopHairList){
                        ShopSummaryPartial shopSummaryPartial = HttpModelConverter.shopHair2ShopSummaryPartial(shopHair);
                        int distance = GPSUtil.getDistance(longitude, latitude, shopHair.getLongitude().doubleValue(), shopHair.getLatitude().doubleValue());
                        shopSummaryPartial.setDistance(distance);

                        shopSummaryPartialList.add(shopSummaryPartial);
                    }
                    result.setResultCode(ResultCode.SUCCESS);
                    result.setNewList(pageIndex == 0);
                    result.setCollectedShopList(shopSummaryPartialList);
                }
                else if (itemType == CollectType.BARBER){
                    List<Barber> barberList = barberService.findBarberList(idList);
                    List<BarberPartial> barberPartialList = new ArrayList<>(barberList.size());
                    for (Barber barber : barberList){
                        BarberPartial barberPartial = HttpModelConverter.barber2BarberPartial(barber);
                        int distance = GPSUtil.getDistance(longitude, latitude, barber.getLongitude().doubleValue(), barber.getLatitude().doubleValue());
                        barberPartial.setDistance(distance);

                        barberPartialList.add(barberPartial);
                    }

                    result.setResultCode(ResultCode.SUCCESS);
                    result.setNewList(pageIndex == 0);
                    result.setCollectedBarberList(barberPartialList);
                }
                else if (itemType == CollectType.BARBER_HAIR){
                    List<BarberHairstyle> barberHairstyleList = barberService.findBarberHairstyleList(idList);
                    List<HairstylePartial> hairstyleProductList = new ArrayList<>(barberHairstyleList.size());
                    for (BarberHairstyle barberHairstyle : barberHairstyleList){
                        HairstylePartial hairstylePartial = HttpModelConverter.barberHairstyle2HairstylePartial(barberHairstyle);
                        hairstyleProductList.add(hairstylePartial);
                    }

                    result.setResultCode(ResultCode.SUCCESS);
                    result.setNewList(pageIndex == 0);
                    result.setCollectedHairstyleList(hairstyleProductList);
                }

                traceLog.error(String.format("CustomerController.collectList() successful -> resultCode:%1$d, ip:%2$s, accessToken:%3$s, itemType:%4$d, pageIndex:%5$d, pageSize:%6$d, longitude:%7$s, latitude:%8$s", ResultCode.SUCCESS, ip, accessToken, itemType, pageIndex, pageSize, longitudeStr, latitudeStr));
            }
            else {
                result.setResultCode(ResultCode.REQUEST_PARAM_ERROR);

                traceLog.error(String.format("CustomerController.collectList() error with REQUEST_PARAM_ERROR -> resultCode:%1$d, ip:%2$s, accessToken:%3$s, itemType:%4$d, pageIndex:%5$d, pageSize:%6$d, longitude:%7$s, latitude:%8$s", ResultCode.REQUEST_PARAM_ERROR, ip, accessToken, itemType, pageIndex, pageSize, longitudeStr, latitudeStr));
            }
        }
        else {
            result.setResultCode(ResultCode.ACCESS_TOKEN_ERROR);
            traceLog.error(String.format("CustomerController.collectList() error with ACCESS_TOKEN_ERROR -> resultCode:%1$d, ip:%2$s, accessToken:%3$s, itemType:%4$d, pageIndex:%5$d, pageSize:%6$d, longitude:%7$s, latitude:%8$s", ResultCode.ACCESS_TOKEN_ERROR, ip, accessToken, itemType, pageIndex, pageSize, longitudeStr, latitudeStr));
        }

        bean2Response(response, result);
    }

    @RequestMapping(value="/v1/customer/coupon/list", method=RequestMethod.POST)
    public void couponList(HttpServletRequest request, HttpServletResponse response){
        CustomerCouponListResponse result = new CustomerCouponListResponse();
        CustomerCouponListRequest customerCouponListRequest = request2Bean(request, CustomerCouponListRequest.class);
        String ip = getIpAddress(request);
        String accessToken = customerCouponListRequest.getAccessToken();
        int listType = customerCouponListRequest.getListType();
        int pageIndex = customerCouponListRequest.getPageIndex();
        int pageSize = customerCouponListRequest.getPageSize();
        CustomerToken customerToken = CustomerTokenHolder.getCurrentCustomerToken();
        if (customerToken != null) {
            long customerId = customerToken.getCustomerId();
            if (RequestParamChecker.checkPageIndexAndSize(pageIndex, pageSize) && (listType == 1 || listType == 2)){
                List<CustomerCoupon> customerCouponList = customerService.findCustomerCouponList(customerId, listType == 2, pageIndex, pageSize);
                List<CouponPartial> couponPartialList = new ArrayList<>(customerCouponList.size());
                for (CustomerCoupon customerCoupon : customerCouponList){
                    CouponPartial couponPartial = HttpModelConverter.CustomerCoupon2CouponPartial(customerCoupon);
                    couponPartialList.add(couponPartial);
                }

                result.setResultCode(ResultCode.SUCCESS);
                result.setCouponlist(couponPartialList);

                traceLog.error(String.format("CustomerController.couponList() successful -> resultCode:%1$d, ip:%2$s, accessToken:%3$s, listType:%4$d, pageIndex:%5$d, pageSize:%6$d", ResultCode.SUCCESS, ip, accessToken, listType, pageIndex, pageSize));
            }
            else {
                result.setResultCode(ResultCode.REQUEST_PARAM_ERROR);
                traceLog.error(String.format("CustomerController.couponList() error with REQUEST_PARAM_ERROR -> resultCode:%1$d, ip:%2$s, accessToken:%3$s, listType:%4$d, pageIndex:%5$d, pageSize:%6$d", ResultCode.REQUEST_PARAM_ERROR, ip, accessToken, listType, pageIndex, pageSize));
            }
        }
        else {
            result.setResultCode(ResultCode.ACCESS_TOKEN_ERROR);
            traceLog.error(String.format("CustomerController.couponList() error with ACCESS_TOKEN_ERROR -> resultCode:%1$d, ip:%2$s, accessToken:%3$s, listType:%4$d, pageIndex:%5$d, pageSize:%6$d", ResultCode.ACCESS_TOKEN_ERROR, ip, accessToken, listType, pageIndex, pageSize));
        }

        bean2Response(response, result);
    }
}
